#ifndef _PROCESS_POOL_HPP
#define _PROCRSS_POOL_HPP

#include <iostream>
#include <vector>
#include <unistd.h>
#include <cstdlib>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>

#include "task_manager.hpp"

class Channel
{
public:
    Channel(int wfd, int subid) : _wfd(wfd), _subid(subid)
    {
        _name = "channel-" + std::to_string(wfd) + "-" + std::to_string(subid);
    }
    std::string get_name()
    {
        return _name;
    }
    int get_wfd()
    {
        return _wfd;
    }
    int get_subid()
    {
        return _subid;
    }
    ~Channel()
    {
    }

private:
    int _wfd;
    pid_t _subid;
    std::string _name;
};

class ChannelManager
{
public:
    ChannelManager()
    {
    }
    ~ChannelManager()
    {
    }
    void print()
    {
        for (auto &c : _channels)
        {
            std::cout << c.get_name() << std::endl;
        }
    }
    void insert(int wfd, int subid)
    {
        _channels.emplace_back(wfd, subid);
    }
    Channel select()
    {
        _next %= _channels.size();
        return _channels[_next++];
    }
    void StopWfd()
    {
        for (auto &c : _channels)
        {
            close(c.get_wfd());
        }
    }

    void WaitSubProcess()
    {
        for (auto &c : _channels)
        {
            waitpid(c.get_subid(), nullptr, 0);
        }
    }

    void StopAndWait()
    {
        //bug :子进程的所有wfd并没有全部关闭
        for (auto &c : _channels)
        {
            //先关闭
            std::cout<<"关闭进程"<<c.get_name()<<std::endl;
            close(c.get_wfd());
            //再回收
            std::cout<<"回收进程"<<c.get_name()<<std::endl;
            waitpid(c.get_subid(), nullptr, 0);
        }

        // //解决方式1：倒着关闭
        // for(int i = _channels.size()-1;i >= 0;i--)
        // {
        //     std::cout<<"关闭进程"<<_channels[i].get_name()<<std::endl;
        //     close(_channels[i].get_wfd());
        //     std::cout<<"回收进程"<<_channels[i].get_name()<<std::endl;
        //     waitpid(_channels[i].get_subid(), nullptr, 0);
        // }
    }
    void CloseAll()
    {
        for (auto &c : _channels)//关闭子进程所有多余的写
        {
            close(c.get_wfd());
        }
    }
    

private:
    std::vector<Channel> _channels;
    int _next = 0; // 采用轮询的方式选择信道
};

class ProcessPool
{
public:
    ProcessPool()
    {
        // 注册任务
        _tm.task_register(download);
        _tm.task_register(upload);
        _tm.task_register(update);
    }
    ~ProcessPool()
    {
    }
    void work(int rfd)
    {
        // 子进程工作 等待|执行任务
        while (true)
        {
            // 接收任务码
            int code = -1;
            ssize_t n = read(rfd, &code, sizeof(code));//通过返回值判断写端是否被关闭，不关闭会一直阻塞，直到读到内容
            // 执行任务
            if(n > 0)
            {
                std::cout << "子进程" << getpid() << "收到任务码" << code << std::endl;
                _tm.execute(code);
            }
            else if(n == 0)
            {
                //子进程退出
                break;
            }
            else
            {
                std::cout<<"读取错误"<<std::endl;
            }
            
        }
    }

    void debug()
    {
        _cm.print();
    }

    void start(int num)
    {
        // 创建num个信道
        for (int i = 1; i <= num; i++)
        {
            // 1.父进程创建管道
            int pipe_fds[2] = {0};
            int n = pipe(pipe_fds);
            if (n < 0)
                return;
            // 2.创建子进程继承管道
            pid_t subid = fork();
            if (subid == -1)
                return;
            else if (subid == 0)
            {
                // 子进程
                // 关闭fds[1],以及其它多余继承父进程的写
                close(pipe_fds[1]);
                _cm.CloseAll();
                work(pipe_fds[0]);

                close(pipe_fds[0]);
                exit(0);
            }
            else
            {
                // 父进程
                // 关闭fds[0]
                close(pipe_fds[0]);
                // 添加信道至Manager
                _cm.insert(pipe_fds[1], subid);
            }
        }
    }
    void send(Channel& ch,int code)
    {
        std::cout << "向子进程" << ch.get_name() << "发送任务码" << code << std::endl;
        write(ch.get_wfd(), &code, sizeof(code));
        sleep(1);
    }
    void run(int cnt)
    {
        while (cnt--)
        {
            // 父进程发送信号给子进程执行任务
            // 选择子进程-轮询
            Channel channel_selected = _cm.select();
            int code = _tm.task_code();
            // 发送任务码
            send(channel_selected,code);
        }
    }
    void stop()
    {
        // // 关闭所有的wfd
        // _cm.StopWfd();
        // std::cout << "关闭wfd" << std::endl;
        // sleep(3);
        // // 等待回收子进程
        // _cm.WaitSubProcess();
        // std::cout << "回收子进程" << std::endl;
        // sleep(3);

        //关闭wfd并回收子进程
        _cm.StopAndWait();
    }
    int default_num = 5;

private:
    ChannelManager _cm;
    TaskManager _tm;
};

#endif